package com.company.oa.announcement.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.company.oa.announcement.dto.AnnouncementDTO;
import com.company.oa.announcement.dto.ScopeDTO;
import com.company.oa.announcement.entity.Announcement;
import com.company.oa.announcement.entity.AnnouncementRead;
import com.company.oa.announcement.entity.AnnouncementScope;
import com.company.oa.announcement.mapper.AnnouncementMapper;
import com.company.oa.announcement.mapper.AnnouncementReadMapper;
import com.company.oa.announcement.mapper.AnnouncementScopeMapper;
import com.company.oa.announcement.service.AnnouncementService;
import com.company.oa.common.exception.BusinessException;
import com.company.oa.common.service.MessageService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class AnnouncementServiceImpl extends ServiceImpl<AnnouncementMapper, Announcement>
        implements AnnouncementService {

    @Autowired
    private AnnouncementScopeMapper scopeMapper;

    @Autowired
    private AnnouncementReadMapper readMapper;

    @Autowired
    private MessageService messageService;

    @Override
    public IPage<Announcement> getAnnouncementPage(int page, int size, Announcement announcement) {
        Page<Announcement> pageParam = new Page<>(page, size);
        return baseMapper.selectAnnouncementPage(pageParam, announcement);
    }

    @Override
    public Announcement getAnnouncementDetail(Long id) {
        return baseMapper.selectAnnouncementDetail(id);
    }

    @Override
    @Transactional
    public boolean createAnnouncement(AnnouncementDTO announcementDTO, Long userId, String userName, Long deptId,
            String deptName) {
        // 创建公告
        Announcement announcement = new Announcement();
        BeanUtils.copyProperties(announcementDTO, announcement);

        announcement.setPublisherId(userId);
        announcement.setPublisherName(userName);
        announcement.setDepartmentId(deptId);
        announcement.setDepartmentName(deptName);
        announcement.setCreateTime(LocalDateTime.now());
        announcement.setReadCount(0);
        announcement.setIsDeleted(0);

        // 如果是草稿状态
        if (announcement.getStatus() == null || announcement.getStatus() == 0) {
            announcement.setStatus(0);
        } else {
            // 如果是发布状态
            announcement.setStatus(1);
            announcement.setPublishTime(LocalDateTime.now());
        }

        // 保存公告
        save(announcement);

        // 保存接收范围
        if (announcementDTO.getScopes() != null && !announcementDTO.getScopes().isEmpty()) {
            saveScopes(announcement.getId(), announcementDTO.getScopes());
        }

        // 如果是发布状态，发送消息通知
        if (announcement.getStatus() == 1) {
            sendNotification(announcement);
        }

        return true;
    }

    @Override
    @Transactional
    public boolean updateAnnouncement(AnnouncementDTO announcementDTO) {
        // 检查公告是否存在
        Announcement existAnnouncement = getById(announcementDTO.getId());
        if (existAnnouncement == null) {
            throw new BusinessException("公告不存在");
        }

        // 只有草稿状态的公告才能修改
        if (existAnnouncement.getStatus() != 0) {
            throw new BusinessException("只有草稿状态的公告才能修改");
        }

        // 更新公告
        Announcement announcement = new Announcement();
        BeanUtils.copyProperties(announcementDTO, announcement);
        announcement.setUpdateTime(LocalDateTime.now());

        // 如果是发布状态
        if (announcement.getStatus() != null && announcement.getStatus() == 1) {
            announcement.setPublishTime(LocalDateTime.now());
        }

        updateById(announcement);

        // 更新接收范围
        if (announcementDTO.getScopes() != null) {
            // 先删除原有范围
            LambdaQueryWrapper<AnnouncementScope> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(AnnouncementScope::getAnnouncementId, announcement.getId());
            scopeMapper.delete(wrapper);

            // 保存新范围
            if (!announcementDTO.getScopes().isEmpty()) {
                saveScopes(announcement.getId(), announcementDTO.getScopes());
            }
        }

        // 如果是发布状态，发送消息通知
        if (announcement.getStatus() != null && announcement.getStatus() == 1) {
            sendNotification(announcement);
        }

        return true;
    }

    @Override
    @Transactional
    public boolean deleteAnnouncement(Long id) {
        // 逻辑删除公告
        Announcement announcement = new Announcement();
        announcement.setId(id);
        announcement.setIsDeleted(1);
        announcement.setUpdateTime(LocalDateTime.now());

        return updateById(announcement);
    }

    @Override
    @Transactional
    public boolean publishAnnouncement(Long id) {
        // 检查公告是否存在
        Announcement existAnnouncement = getById(id);
        if (existAnnouncement == null) {
            throw new BusinessException("公告不存在");
        }

        // 只有草稿状态的公告才能发布
        if (existAnnouncement.getStatus() != 0) {
            throw new BusinessException("只有草稿状态的公告才能发布");
        }

        // 更新公告状态
        Announcement announcement = new Announcement();
        announcement.setId(id);
        announcement.setStatus(1);
        announcement.setPublishTime(LocalDateTime.now());
        announcement.setUpdateTime(LocalDateTime.now());

        boolean result = updateById(announcement);

        // 发送消息通知
        if (result) {
            existAnnouncement.setStatus(1);
            existAnnouncement.setPublishTime(LocalDateTime.now());
            sendNotification(existAnnouncement);
        }

        return result;
    }

    @Override
    @Transactional
    public boolean cancelAnnouncement(Long id) {
        // 检查公告是否存在
        Announcement existAnnouncement = getById(id);
        if (existAnnouncement == null) {
            throw new BusinessException("公告不存在");
        }

        // 只有已发布状态的公告才能撤销
        if (existAnnouncement.getStatus() != 1) {
            throw new BusinessException("只有已发布状态的公告才能撤销");
        }

        // 更新公告状态
        Announcement announcement = new Announcement();
        announcement.setId(id);
        announcement.setStatus(3); // 已撤销
        announcement.setUpdateTime(LocalDateTime.now());

        return updateById(announcement);
    }

    @Override
    @Transactional
    public boolean topAnnouncement(Long id, boolean isTop) {
        // 检查公告是否存在
        Announcement existAnnouncement = getById(id);
        if (existAnnouncement == null) {
            throw new BusinessException("公告不存在");
        }

        // 更新公告置顶状态
        Announcement announcement = new Announcement();
        announcement.setId(id);
        announcement.setIsTop(isTop ? 1 : 0);

        if (isTop) {
            // 默认置顶7天
            announcement.setTopEndTime(LocalDateTime.now().plusDays(7));
        } else {
            announcement.setTopEndTime(null);
        }

        announcement.setUpdateTime(LocalDateTime.now());

        return updateById(announcement);
    }

    @Override
    public List<Announcement> getUserAnnouncements(Long userId, Long departmentId, List<Long> roleIds) {
        return baseMapper.selectUserAnnouncements(userId, departmentId, roleIds);
    }

    @Override
    @Transactional
    public boolean readAnnouncement(Long id, Long userId, String userName, String ip) {
        // 检查是否已读
        LambdaQueryWrapper<AnnouncementRead> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AnnouncementRead::getAnnouncementId, id)
                .eq(AnnouncementRead::getUserId, userId);

        if (readMapper.selectCount(wrapper) > 0) {
            return true; // 已读，直接返回
        }

        // 添加阅读记录
        AnnouncementRead read = new AnnouncementRead();
        read.setAnnouncementId(id);
        read.setUserId(userId);
        read.setUserName(userName);
        read.setReadTime(LocalDateTime.now());
        read.setReadIp(ip);

        readMapper.insert(read);

        // 更新公告阅读次数
        Announcement updateAnnouncement = new Announcement();
        updateAnnouncement.setId(id);
        // 获取当前公告
        Announcement currentAnnouncement = getById(id);
        updateAnnouncement.setReadCount(currentAnnouncement.getReadCount() + 1);
        updateById(updateAnnouncement);
        return true;
    }

    @Override
    public Map<String, Object> getAnnouncementStats() {
        Map<String, Object> result = new HashMap<>();

        // 按类型统计
        List<Map<String, Object>> typeStats = baseMapper.selectAnnouncementStatsByType();
        result.put("typeStats", typeStats);

        // 按部门统计
        List<Map<String, Object>> deptStats = baseMapper.selectAnnouncementStatsByDepartment();
        result.put("deptStats", deptStats);

        return result;
    }

    /**
     * 保存公告接收范围
     */
    private void saveScopes(Long announcementId, List<ScopeDTO> scopeDTOs) {
        List<AnnouncementScope> scopes = new ArrayList<>();

        for (ScopeDTO scopeDTO : scopeDTOs) {
            AnnouncementScope scope = new AnnouncementScope();
            scope.setAnnouncementId(announcementId);
            scope.setScopeType(scopeDTO.getScopeType());
            scope.setScopeId(scopeDTO.getScopeId());
            scope.setScopeName(scopeDTO.getScopeName());
            scope.setCreateTime(LocalDateTime.now());

            scopes.add(scope);
        }

        for (AnnouncementScope scope : scopes) {
            scopeMapper.insert(scope);
        }
    }

    /**
     * 发送消息通知
     */
    private void sendNotification(Announcement announcement) {
        // 获取公告接收范围
        LambdaQueryWrapper<AnnouncementScope> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AnnouncementScope::getAnnouncementId, announcement.getId());
        List<AnnouncementScope> scopes = scopeMapper.selectList(wrapper);

        if (scopes == null || scopes.isEmpty()) {
            return;
        }

        // 构建消息内容
        String title = "新公告: " + announcement.getTitle();
        String content = "您有一条新的公告，请及时查看。";

        // 根据范围发送消息
        for (AnnouncementScope scope : scopes) {
            switch (scope.getScopeType()) {
                case 1: // 全员
                    messageService.sendSystemMessageToAll(title, content,
                            "/announcement/detail/" + announcement.getId());
                    break;
                case 2: // 部门
                    messageService.sendSystemMessageToDepartment(title, content,
                            "/announcement/detail/" + announcement.getId(), scope.getScopeId());
                    break;
                case 3: // 角色
                    messageService.sendSystemMessageToRole(title, content,
                            "/announcement/detail/" + announcement.getId(), scope.getScopeId());
                    break;
                case 4: // 个人
                    messageService.sendSystemMessage(title, content, "/announcement/detail/" + announcement.getId(),
                            scope.getScopeId());
                    break;
                default:
                    break;
            }
        }
    }
}